#pragma once

#include <iostream>
#include <cstring>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Log.hpp"
using namespace MyLogModule;
const uint16_t g_port = 8080;

class TcpServer
{
private:
    void HandleTask(int sockfd)
    {
        char buffer[2048];
        while(true)
        {
            //接收客户端发来的信息
            int n = ::read(sockfd,&buffer,sizeof(buffer)-1);
            if(n > 0)
            {
                buffer[n] = 0;
                LOG(NORMAL) << buffer;

                std::string message = "echo#";
                message += buffer;

                //将消息回显给客户端
                ::write(sockfd,message.c_str(),message.size());
            }
        }
    }

public:
    TcpServer()
    {}
    ~TcpServer()
    {}
    void Init()
    {
        // 1.创建socket
        _listenSocket= ::socket(AF_INET, SOCK_STREAM, 0);
        if (_listenSocket < 0)
        {
            LOG(FATAL) << "create socker fail";
            return;
        }
        LOG(FATAL) << "create socker success";

        sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_addr.s_addr = INADDR_ANY;
        local.sin_port = ::htons(g_port);
        // 2. 绑定
        int n = ::bind(_listenSocket, (sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            LOG(FATAL) << "bind fail";
            return;
        }
        LOG(FATAL) << "bind success";

        // 3.tcp是面向连接的，就要求tcp随时随地等待被连接
        // 因此，要设置为监听状态
        n = ::listen(_listenSocket, 4); // 第二个参数表示：服务器中客户端连接的个数
        if (n < 0)
        {
            LOG(FATAL) << "listen fail";
            return; 
        }
        LOG(FATAL) << "listen success";
    }

    void Start()
    {
        while(true)
        {
            sockaddr_in from;   //用来存放接受连接的客户端的地址信息
            socklen_t len = sizeof(from);
            //_listenSocket正在监听的socket     （拉客的）
            //返回值是一个socket,即所接待的人的fd (接待的服务员)
            int sockfd = ::accept(_listenSocket,(sockaddr*)&from,&len);     //没有人连接则阻塞
            if(sockfd < 0)
            {
                LOG(FATAL) << "accept fail";
                continue;       //当前socket监听失败，则继续监听其它的!!!
            }

            //处理
            HandleTask(sockfd);
        }
    }
private:
    int _listenSocket;
};